using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using System.Reflection;
namespace KLib
{
    public class Reflection
    {
        static public void Reflect(Game game, object obj)
        {
            #region [RequiredService] | [OptionalService]
            FieldInfo[] fields = obj.GetType().GetFields();
            PropertyInfo[] properties = obj.GetType().GetProperties();

            foreach (FieldInfo field in fields)
            {
                object[] attributes = field.GetCustomAttributes(true);
                foreach (object attr in attributes)
                {
                    RequiredServiceAttribute requiredService = attr as RequiredServiceAttribute;
                    OptionalServiceAttribute optionalService = attr as OptionalServiceAttribute;

                    if (requiredService != null)
                    {
                        Type serviceType = requiredService.serviceType ?? field.FieldType;
                        object service = game.Services.GetService(serviceType);

                        if (service == null)
                            throw new Exception(string.Format("No service of type {0} found.", serviceType));
                        field.SetValue(obj, service);
                    }
                    else if (optionalService != null)
                    {
                        Type serviceType = optionalService.serviceType ?? field.FieldType;
                        object service = game.Services.GetService(serviceType);

                        if (service != null)
                            field.SetValue(obj, service);
                    }
                }
            }

            foreach (PropertyInfo property in properties)
            {
                object[] attributes = property.GetCustomAttributes(true);
                foreach (object attr in attributes)
                {
                    RequiredServiceAttribute requiredService = attr as RequiredServiceAttribute;
                    OptionalServiceAttribute optionalService = attr as OptionalServiceAttribute;

                    if (requiredService != null)
                    {
                        Type serviceType = requiredService.ServiceType ?? property.PropertyType;
                        object service = game.Services.GetService(serviceType);

                        if (service == null)
                            throw new Exception(string.Format("No Service of type {0} found.", serviceType));
                        property.SetValue(obj, service, null);
                    }
                    else if (optionalService != null)
                    {
                        Type serviceType = optionalService.ServiceType ?? property.PropertyType;
                        object service = game.Services.GetService(serviceType);

                        if (service != null)
                            property.SetValue(obj, service, null);
                    }
                }
            }
            #endregion

            #region [RegistersService]
            MemberInfo info = obj.GetType();
            object[] registersServiceAttrubutes = info.GetCustomAttributes(typeof(RegistersServiceAttribute), true);
            for (int i = 0; i < registersServiceAttrubutes.Length; i++)
            {
                RegistersServiceAttribute registersService = (RegistersServiceAttribute)registersServiceAttrubutes[i];
                game.Services.AddService(registersService.serviceType, obj);

            }

            #endregion
        }
    }
}
